package com.gxy.learn.cu.utils.io;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.IOUtils;

import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;

/**
 * Description(文件操作类)
 * author: Gao xueyong
 * Create at: 2021/7/18 下午4:43
 */
@Slf4j
public class FileUtils {
    /**
     * 传统读取文件为二进制数组
     *
     * @param filePath
     * @return
     */
    private static byte[] readFilePathToByte(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            return null;
        }
        byte[] result = new byte[(int) file.length()];
        FileInputStream fis = new FileInputStream(file);
        fis.read(result);
        fis.close();
        return result;
    }

    /**
     * Nio 形式读取文件为二进制数组
     *
     * @param filePath
     * @return
     */
    public static byte[] readFilePathToByteNIO(String filePath) throws IOException {
        return Files.readAllBytes(new File(filePath).toPath());
//        or
//        return Files.readAllBytes(Paths.get(filePath));
    }


    public static void writeBytesToFile(byte[] bytes, String fileDest) {
        try (FileOutputStream fileOutputStream = new FileOutputStream(fileDest)) {
            fileOutputStream.write(bytes);
        } catch (Exception e) {
            log.error("byate转换文件失败！", e);
        }
    }


    public static void writeBytesToFileNio(byte[] bytes, String fileDest) {
        try {
            Path path = Paths.get(fileDest);
            Files.write(path, bytes);
        } catch (Exception e) {
            log.error("byate转换文件失败！", e);
        }
    }


    /**
     * 生成zip文件 一层文件夹 如
     *  文档
     *      文档1.txt
     *      文档2.txt
     *      文档3.xlsx
     *  头像
     *      head1.jpg
     *      head2.jpg
     *      head3.jpg
     * @param fileMap{文件夹名称:[文件路径]}
     * @return
     */
    public static byte[] toZip(Map<String, List<String>> fileMap) {
        ArchiveOutputStream os = null;
        ByteArrayOutputStream zipOut = null;
        try {
            zipOut = new ByteArrayOutputStream();
            os = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.ZIP, zipOut);
            for (Map.Entry<String, List<String>> entry : fileMap.entrySet()) {
                for (String tempFilePath : entry.getValue()) {
                    String pathAry[] = tempFilePath.split("\\/");
//                    目录 如  头像/head.jpg
                    os.putArchiveEntry(new ZipArchiveEntry(String.format("%s/%s", entry.getKey(), pathAry[pathAry.length - 1])));
                    //文件二进制数组
                    IOUtils.copy(new ByteArrayInputStream(FileUtils.readFilePathToByteNIO(tempFilePath)), os);
                    os.closeArchiveEntry();
                }
            }
            os.close();
            zipOut.close();
            return zipOut.toByteArray();
        } catch (Exception e) {
            log.error("生成zip文件失败！");
            IOUtils.closeQuietly(os);
            IOUtils.closeQuietly(zipOut);
            return null;
        }
    }


    /**
     * 读取远程文件并并返回
     * @param fileUrl  http://xxx.xxx.xxx.xxx:80/group1/M00/00/22/wKgUvWK66jmAL9AXAAEbNRY2TjY93.docx
     * @return
     */

    public static File readRemoteFile(String fileUrl) throws IOException {
        if(StringUtils.isBlank(fileUrl)){
            log.error("文件地址为空！");
            return null;
        }
        File file = null;
        try{
            String[] fileUrlAry = fileUrl.split("\\/");
            String[] relFile = fileUrlAry[fileUrlAry.length-1].split("\\.");
            String prefix = relFile[0];
            String suffix = relFile[1];
            file = File.createTempFile(prefix,String.format(".%s",suffix));
        }catch (Exception e){
            log.error("文件地址[{}]错误！未解析到文件名称！",fileUrl,e);
            return null;
        }
        if(null == file){
            log.error("文件地址[{}]错误！未能创建本地临时文件！",fileUrl);
            return null;
        }

        InputStream inputStream = null;
        FileOutputStream outputStream = null;
        try  {
            URL url = new URL(fileUrl);
            inputStream = url.openStream();
            outputStream = new FileOutputStream(file);
            // commons-io
            IOUtils.copy(inputStream, outputStream);
//            log.info("path = {}",file.getAbsolutePath());
            return file;
        }catch (Exception e){
            log.error("根据远程文件地址[{}]生成本地文件失败！",fileUrl,e);
            return null;
        }finally {
            IOUtils.closeQuietly(inputStream);
            IOUtils.closeQuietly(outputStream);
        }
    }


    public static void main(String[] args) throws IOException {
//        String path = "/Users/gaoxueyong/Documents/export/Macbook.mp4";
//        String destPath = "/Users/gaoxueyong/Documents/export/Macbook-bak.mp4";
//        long start = System.currentTimeMillis();
//        writeBytesToFile(readFilePathToByte(path), destPath);
//        log.info("生成文件耗时！{}", System.currentTimeMillis() - start);
//        start = System.currentTimeMillis();
//        destPath = "/Users/gaoxueyong/Documents/export/Macbook-nio-bak.mp4";
//        writeBytesToFileNio(readFilePathToByteNIO(path), destPath);
//        log.info("生成文件耗时！NIO {}", System.currentTimeMillis() - start);
//        readRemoteFile("http://rongcloud-web.qiniudn.com/docs_demo_rongcloud_logo.png");
    }

}
